#include <string.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

#include "utils.h"
#include "patch.h"

extern void _ZdaPv(void *ptr);

char *(*fileIO_GetResourcePath)(void *this, const char *filename);

char *fileIO_GetVideoPath(fileIO *this, const char *filename)
{
	this->tmpPath[0] = 0;
	if (!filename)
		return this->tmpPath;

	strcpy(this->tmpPath, this->videoPath);
	int len = strlen(this->tmpPath);
	if (len >= 1)
	{
		if (this->tmpPath[len - 1] != '/')
		{
			this->tmpPath[len++] = '/';
			this->tmpPath[len] = '\0';
		}
	}
	// printf("video_dir: %s, filename: %s\n", this->tmpPath, filename);
	strcat(this->tmpPath, filename);

	char *p = strrchr(this->tmpPath, '.');
	if (p++)
	{
		if (strcasecmp(p, "bik") == 0)
		{
			strcpy(p, "mp4");
			if (!file_exists(this->tmpPath))
				strcpy(p, "bik");
		}
	}

	printf("fileIO_GetVideoPath: filename: %s; return: %s\n", filename, this->tmpPath);

	return this->tmpPath;
}

int GetInterPath(char *path)
{
	fileIO *fileIo = (fileIO *)FILEIO_ADDRESS;
	int *LangID = (int *)(LOAD_ADDRESS + 0x001C85A8);
	int *FONT_USE_GB = (int *)(LOAD_ADDRESS + 0x001C85A4);

	*LangID = Android_JNI_GetLocalID();
	if (*LangID == 0)
	{
		*FONT_USE_GB = 0;
		snprintf(fileIo->langPath, 1024, "%s/zh-Hant", DATA_PATH);
	}
	else
	{
		*FONT_USE_GB = 1;
		snprintf(fileIo->langPath, 1024, "%s/zh-Hans", DATA_PATH);
	}

	strcpy(path, DATA_PATH);
	return 0;
}

char *fileIO_GetCachePathById(fileIO *this, int id)
{
	snprintf(this->tmpPath, 1024, "%s/%d.cm", GAME_CACHE_PATH, id);
	debugPrintf("GetCachePath: %s\n", this->tmpPath);
	return this->tmpPath;
}

int cFILE_CloseView(cFILE *this, void *a2)
{
	if (!this)
		return 1;

	if (this->mmap_addr && this->mmap_addr != (void *)-1)
		free(this->mmap_addr);

	this->is_mmap_view = 0;
	this->mmap_addr = 0;
	this->read_data = 0;
	this->read_offset = 0;
	this->read_size = 0;

	if (this->file_fd > 0)
		close(this->file_fd);

	this->is_mmap_mode = 0;
	this->file_fd = 0;

	return 1;
}

int cFILE_CloseMapping(cFILE *this)
{
	if (!this)
		return 1;

	cFILE_CloseView(this, 0);

	return 1;
}

int cFILE_Close(cFILE *this)
{
	if (!this)
		return 1;

	cFILE_CloseMapping(this);

	if (this->file_handle)
		fclose(this->file_handle);

	this->is_fopen_mode = 0;
	this->file_handle = 0;
	this->file_size = 0;

	if (this->file_path)
		_ZdaPv(this->file_path);
	this->file_path = 0;

	this->unk_32 = 0;
	this->unk_36 = 0;
	this->unk_40 = 0;
	this->unk_44 = 0;
	this->unk_48 = 0;
	this->unk_52 = 0;
	this->unk_56 = 0;
	this->unk_60 = 0;
	this->unk_64 = 0;
	this->unk_68 = 0;
	this->unk_72 = 0;
	this->unk_76 = 0;
	this->unk_80 = 0;
	this->unk_84 = 0;
	this->unk_88 = 0;
	this->unk_92 = 0;

	return 1;
}

int cFILE_set_EOF(cFILE *this)
{
	if (!this->file_handle || !this->file_path)
		return 0;

	return truncate(this->file_path, ftell(this->file_handle)) != -1;
}

int initPatchFile()
{
	fileIO_GetResourcePath = (void *)so_symbol(&so_mod, "_ZN6fileIO15GetResourcePathEPKc");

	hook_addr(so_symbol(&so_mod, "_ZN6fileIO12GetVideoPathEPKc"), (uintptr_t)&fileIO_GetVideoPath);
	hook_addr(so_symbol(&so_mod, "_Z12GetInterPathPc"), (uintptr_t)&GetInterPath);

	hook_addr(so_symbol(&so_mod, "_ZN6fileIO12GetCachePathEi"), (uintptr_t)&fileIO_GetCachePathById);

	hook_addr(so_symbol(&so_mod, "_ZN5cFILE9CloseViewEPv"), (uintptr_t)&cFILE_CloseView);
	hook_addr(so_symbol(&so_mod, "_ZN5cFILE12CloseMappingEv"), (uintptr_t)&cFILE_CloseMapping);
	hook_addr(so_symbol(&so_mod, "_ZN5cFILE5CloseEv"), (uintptr_t)&cFILE_Close);
	hook_addr(so_symbol(&so_mod, "_ZN5cFILE7set_EOFEv"), (uintptr_t)&cFILE_set_EOF);

	return 0;
}
